import { initProps } from "./componentProps.js";
import { proxyRefs, reactive } from "../reactivity/index.js";
import { isFunction, isObject } from "../shared/index.js";

export let currentInstance = null;

export const setCurrentInstance = (instance) => (currentInstance = instance);
export const getCurrentInstance = () => currentInstance;

export function createInstance(n2, parentComponent) {
  const instance = {
    // 组件的实例,用它来记录组件中的属性
    setupState: {},
    state: {},
    isMounted: false, // 是否挂载成功
    vnode: n2, // 组件的虚拟节点
    subTree: null, // 组件渲染的虚拟节点
    update: null, // 用于组件更新的方法
    propsOptions: n2.type.props,
    props: {},
    attrs: {},
    slots: {},
    ctx: {}, // 这个ctx 是用来保存方法的
    parent: parentComponent,
    provides: parentComponent ? parentComponent.provides : Object.create(null),
    render: null,
    proxy: null, // 帮我们做代理 -> proxyRefs
  };
  return instance;
}

function initSlots(instance, children) {
  instance.slots = children;
}

export function setupComponent(instance) {
  let { type, props, children } = instance.vnode;
  const publicProperties = {
    $attrs: (instance) => instance.attrs,
    $props: (instance) => instance.$props,
    $slots: (instance) => instance.slots,
  };
  instance.proxy = new Proxy(instance, {
    get(target, key) {
      const { state, props, setupState } = target;
      if (key in state) {
        return state[key];
      } else if (key in setupState) {
        return setupState[key];
      } else if (key in props) {
        return props[key];
      }
      const getter = publicProperties[key];
      if (getter) {
        return getter(instance); // 将instance传递进去
      }
    },
    set(target, key, value) {
      const { state, props, setupState } = target;
      if (key in state) {
        state[key] = value;
        return true;
      } else if (key in setupState) {
        setupState[key] = value;
        return true;
      } else if (key in props) {
        console.warn(`mutate prop ${key} not allowed, props are readonly`);
        return false;
      }
      return true;
    },
  });
  initProps(instance, props);
  initSlots(instance, children);

  const setup = type.setup; // 用户编写的setup方法
  if (setup) {
    // 将自己放在全局上 instance
    setCurrentInstance(instance);
    const setupResult = setup(instance.props, {
      attrs: instance.attrs,
      slots: instance.slots,
      emit: (eventName, ...args) => {
        // onMyEvent
        let handler =
          props[`on${eventName[0].toUpperCase()}${eventName.slice(1)}`];
        handler && handler(...args);
      },
      expose: () => {},
    });
    // 移除instance
    setCurrentInstance(null);

    if (isObject(setupResult)) {
      // 返回的是setup提供的数据源
      instance.setupState = proxyRefs(setupResult);
    } else if (isFunction(setupResult)) {
      instance.render = setupResult;
    }
  }

  const data = type.data;
  if (data) {
    instance.state = reactive(data());
  }
  !instance.render && (instance.render = type.render);
}
